#include <cstddef>
#include <cstdio>
#include <ctime>
#include <exception>
#include <fmt/format.h>
#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
using namespace std;

class FileError : public std::exception {
public:
  FileError(string filename) : m_filename{std::move(filename)} {}
  const char *what() const noexcept override { return m_message.c_str(); }
  virtual const string &getFilename() const noexcept { return m_filename; }

protected:
  virtual void setMessage(string message) { m_message = message; }

private:
  string m_filename;
  string m_message;
};

class FileOpenError : public FileError {
public:
  FileOpenError(string filename) : FileError(std::move(filename)) {
    setMessage("File open error!" + getFilename());
  }
};

class FileReadError : public FileError {
public:
  FileReadError(string filename, size_t linenumber)
      : FileError{std::move(filename)}, m_lineNumber{linenumber} {
    setMessage(
        fmt::format("Error reading {},line {}.", getFilename(), linenumber));
  }

  virtual size_t getLineNumber() const noexcept { return m_lineNumber; }

private:
  size_t m_lineNumber{0};
};

vector<int> readIntegerFile(string filename) {
  ifstream inputstream{filename.data()};
  if (inputstream.fail()) {
    throw FileOpenError{filename};
  }
  vector<int> integers;
  std::size_t lineNumber{0};
  while (!inputstream.eof()) {
    string line;
    getline(inputstream, line);
    ++lineNumber;

    istringstream lineStream{line};
    int temp;
    while (lineStream >> temp) {
      integers.push_back(temp);
    }
    if (!lineStream.eof()) {
      throw FileReadError(filename, lineNumber);
    }
  }
  return integers;
}
int main() {
  try {
    string filename = "c:/windows/win.ini";
    vector<int> myInts = readIntegerFile(filename);
  } catch (const FileError &e) {
    cerr << e.what() << endl;
    return 1;
  }
}